#include "mm.h"
#include "kernel.h"
#include "stdio.h"

static u32 addr_stack;

// initialized the virtual address manager and pushes available
// page address onto the stack for when we need them
void init_virt_mm() {
  u32 old_esp, i;
  addr_stack = VIRT_ADDR_STACK;
  __asm__ volatile("mov %%esp, %0" : "=r" (old_esp));
  __asm__ volatile("mov %0, %%esp" : : "r" (addr_stack));
  // push error code first so we know if weve run out of addresses
  __asm__ volatile("pushl %0" : : "r" (MM_ERROR_MAGIC));

  // start pushing available virtual addresses onto the stack
  for(i = KERNEL_VIRT_END; i < KERNEL_VIRT_END + 0x00100000; i += 0x1000) 
    __asm__ volatile("pushl %0" : : "r" (i));

  __asm__ volatile("mov %%esp, %0" : "=r" (addr_stack));
  __asm__ volatile("mov %0, %%esp" : : "r" (old_esp));
}

u32 get_page() {
  u32 old_esp, page;
  __asm__ volatile("mov %%esp, %0" : "=r" (old_esp));
  __asm__ volatile("mov %0, %%esp" : : "r" (addr_stack));
  __asm__ volatile("popl %0" : "=r" (page));
  __asm__ volatile("mov %%esp, %0" : "=r" (addr_stack));
  __asm__ volatile("mov %0, %%esp" : : "r" (old_esp));
  // panic if were out of tables
  if(page == MM_ERROR_MAGIC)
    kpanic("PANIC at get_page()! No more virtual addresses available");

  return page;
}

void free_page(u32 page) {
  u32 old_esp;
  __asm__ volatile("mov %%esp, %0" : "=r" (old_esp));
  __asm__ volatile("mov %0, %%esp" : : "r" (addr_stack));
  __asm__ volatile("pushl %0" : : "r" (page));
  __asm__ volatile("mov %%esp, %0" : "=r" (addr_stack));
  __asm__ volatile("mov %0, %%esp" : : "r" (old_esp));
}

void debug_virt_mm() {
  kprintf("virtual address stack: %x\n", addr_stack);
}
  
